package me.magicall.test.backup;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileChannel;

import org.springframework.web.multipart.MultipartFile;

public class FileUtil {

	public static final String SWF = ".swf";
	public static final String MP3 = ".mp3";
	public static final String GIF = ".gif";
	public static final String JPG = ".jpg";
	public static final String PNG = ".png";

	public static final FileUtil FILE = new FileUtil();

	private FileUtil() {

	}

	public byte[] readRAM(final File f) throws IOException {
		return readRAM(new FileInputStream(f), (int) f.length());
	}

	/**
	 * Reads <code>length</code> of bytes of content of the given <code>InputStream</code> into an array.
	 * <p>
	 * This method currently does not check for maximum length and might cause a java.lang.OutOfMemoryError. It is only intended for performance-measurements of data-based algorithms that want to exclude I/O-usage.
	 * <p>
	 * 
	 * @param in
	 * the input stream to read.
	 * @param length
	 * the amount of bytes to read from the input stream.
	 * @throws IOException
	 * if sth goes wrong.
	 */
	public byte[] readRAM(final InputStream in, final int length) throws IOException {
		final byte[] ret = new byte[length];
		try {
			int offset = 0;
			int read = 0;
			do {
				read = in.read(ret, offset, length - read);
				if (read > 0) {
					offset += read;
				}
			} while (read != -1 && offset != length);
			return ret;
		} finally {
			in.close();
		}
	}

	public boolean copyFile(final File src, final File target) {
		return copyFile(src, target, FileExistOption.DO_NOTHING);

	}

	/**
	 * 把第一个参数的file复制到第二个参数代表的路径去.
	 * 注:若第二个参数代表的file存在,将会被覆盖;若不存在,则会创建
	 * 
	 * @param src
	 * @param target
	 * @return
	 */
	public boolean copyFile(final File src, final File target, final FileExistOption option) {
		if (target.exists()) {
			if (option == FileExistOption.DO_NOTHING) {
				return false;
			} else if (option == FileExistOption.REWRITE) {
				if (!target.delete()) {
					return false;
				}
			}
		}
		//检查父目录
		tryMakeDirs(target.getParentFile());

		FileInputStream fin = null;
		FileOutputStream fout = null;
		FileChannel in = null, out = null;
		try {
			fin = new FileInputStream(src);
			fout = new FileOutputStream(target, option == FileExistOption.APPEND);
			in = fin.getChannel();
			out = fout.getChannel();
			out.transferFrom(in, 0, src.length());
			return true;
		} catch (final Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (final IOException e) {
					e.printStackTrace();
				}
			}
			if (out != null) {
				try {
					out.close();
				} catch (final IOException e) {
					e.printStackTrace();
				}
			}
			if (fin != null) {
				try {
					fin.close();
				} catch (final IOException e) {
					e.printStackTrace();
				}
			}
			if (fout != null) {
				try {
					fout.close();
				} catch (final IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public boolean tryMakeDirs(final String fileName) {
		return tryMakeDirs(new File(fileName).getParentFile());
	}

	public boolean tryMakeDirs(final File dir) {
		if (!dir.exists()) {
			if (!dir.mkdirs()) {
				return false;
			}
		} else if (dir.isFile()) {
			return false;
		}
		return true;
	}

	public void makeDirs(final File dir) throws IOException {
		if (!dir.exists()) {
			if (!dir.mkdirs()) {
				throw new IOException("不能创建目录:" + dir.getAbsolutePath());
			}
		} else if (dir.isFile()) {
			throw new IOException("不是目录:" + dir.getAbsolutePath());
		}
	}

	public void makeDirs(final String fileName) throws IOException {
		makeDirs(new File(fileName).getParent());
	}

	public File makeFile(final String fileName) throws IOException {
		makeDirs(fileName);
		return new File(fileName);
	}

	public File uploadFile(final MultipartFile file, final String dirPath, final String suffix) {
		File tmpFile = null;
		try {
			final File dir = new File(dirPath);

			boolean mkdirSuccess = true;
			if (!dir.isDirectory()) {
				synchronized (FileUtil.class) {
					if (!dir.isDirectory()) {
						mkdirSuccess = dir.mkdirs();
					}
				}
			}

			if (!mkdirSuccess) {
				return null;
			}

			tmpFile = CommonUtil.createTmpFile();
			try {
				file.transferTo(tmpFile);
			} catch (final IllegalStateException e1) {
				e1.printStackTrace();
				return null;
			} catch (final IOException e1) {
				e1.printStackTrace();
				return null;
			}

			try {
				final File target = new File(dir, Md5Util.md5(tmpFile) + "." + suffix);
				if (copyFile(tmpFile, target, FileExistOption.REWRITE)) {
					return target;
				} else {
					return null;
				}
			} catch (final Exception e) {
				e.printStackTrace();
				return null;
			}
		} finally {
			if (tmpFile != null) {
				try {
					tmpFile.delete();
				} catch (final Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void main(final String[] args) {
		FileUtil.FILE.copyFile(new File("D:\\MediaID.bin"), new File("D:\\absdiel"), FileExistOption.REWRITE);
	}
}
